
import 'package:collection/collection.dart';
import 'package:easy_refresh/easy_refresh.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:im_app/im/util/DbUtil.dart';

import '../../dao/ImUserDao.dart';
import '../../pojo/Enums.dart';
import '../../pojo/ImPojo.dart';

final class UserListCubit extends Cubit<UserListState> {
  UserListCubit() : super(const UserListState.loading());

  //

  int _pageStart = 0;
  final _pageSize = 100;

  Future<void> loadData() async {
    try {
      final userDao = ImUserDao();

      _pageStart = 0;
      final users = await userDao.getNewByStartId(this._pageStart, _pageSize);
      var letterInfo = UserListState.buildLetters(users);
      emit(UserListState.success(users, letterInfo.letters, letterInfo.letterSizeMap));
    } on Exception {
      emit(const UserListState.failure());
    }
  }

  Future<IndicatorResult> loadMoreData() async {
    try {
      final userDao = ImUserDao();
      this._pageStart = state.users.length;
      final users = await userDao.getNewByStartId(this._pageStart, _pageSize);
      if (users.isEmpty) {
        return IndicatorResult.noMore;
      }
      final List<ImUser> lastedUsers = List.of(state.users);
      lastedUsers.addAll(users);
      var letterInfo = UserListState.buildLetters(lastedUsers);
      emit(UserListState.success(lastedUsers, letterInfo.letters, letterInfo.letterSizeMap));
      return IndicatorResult.success;
    } on Exception {
      emit(const UserListState.failure());
      return IndicatorResult.fail;
    }
  }
}

final class UserListState extends Equatable {
  final LoadingState state;
  final List<ImUser> users;
  final List<String> letters;
  final Map<String, int> letterSizeMap;

  const UserListState._({
    this.state = LoadingState.loading,
    this.users = const <ImUser>[],
    this.letters = const <String>[],
    this.letterSizeMap = const {},
  });

  const UserListState.loading() : this._();

  const UserListState.success(List<ImUser> users, List<String> letters, Map<String, int> letterSizeMap)
      : this._(state: LoadingState.success, users: users, letters: letters, letterSizeMap: letterSizeMap);

  const UserListState.failure() : this._(state: LoadingState.failure);

  @override
  List<Object?> get props => [state, users];

  static LetterInfo buildLetters(List<ImUser> users) {
    Map<String, List<ImUser>> grouped = groupBy(users, (value) => value.firstLetter??'');
    var newLetter = <String>[];
    var _letterSizeMap = Map<String, int>();
    grouped.forEach((key, value){
      _letterSizeMap[key] = value.length;
      print('$key size: ${value.length}');
      newLetter.add(key);
    });
    newLetter.sort((k1, k2)=>Comparable.compare(k1, k2));
    return LetterInfo(letters: newLetter, letterSizeMap: _letterSizeMap);
  }
}

final class LetterInfo {
  final List<String> letters;
  final Map<String, int> letterSizeMap;

  const LetterInfo({required this.letters, required this.letterSizeMap});
}



